package com.personal.dataanalyse.reportmanage.builder.impl;

import java.util.List;

import com.personal.core.data.DataTable;
import com.personal.core.utils.Assert;
import com.personal.core.utils.CoreUtil;
import com.personal.dataanalyse.reportmanage.base.DataAnalyseModel;
import com.personal.dataanalyse.reportmanage.base.DataChartModel;
import com.personal.dataanalyse.reportmanage.builder.ModelBuilder;
import com.personal.dataanalyse.reportmanage.builder.ModelFiller;
import com.personal.dataanalyse.reportmanage.entity.ReportHeader;
import com.personal.dataanalyse.reportmanage.util.ModelUtil;
import com.personal.dataanalyse.util.DeepCopyUtil;
import com.personal.dataconvert.DataSet2Excel;
import com.personal.dataconvert.bean.HtmlConfig;
import com.personal.dataconvert.bean.SheetConfig;
import com.personal.dataconvert.bean.WorkBookConfig;
import com.personal.dataconvert.util.ExcelHtmlUtil;

/**
 * 构建实现实现
 * @author cuibo
 *
 */
public class ModelBuilderImpl implements ModelBuilder
{
    
    /**
     * 模型
     */
    private DataAnalyseModel model;
    
    /** 报表结果 */
    private DataTable table;
    
    /** 表头配置 */
    private List<ReportHeader> headerConfigs;
    
    /** 是否填充数据 */
    private boolean fillData;
    
    /**
     * 
     * @param model   模型
     * @throws Exception
     */
    public ModelBuilderImpl(DataAnalyseModel model) throws Exception
    {
        this(model, true);
    }
    
    /**
     * 
     * @param model   模型
     * @param fillData   是否填充数据
     * @throws Exception
     */
    public ModelBuilderImpl(DataAnalyseModel model, boolean fillData) throws Exception
    {
        this(model, fillData, null, null);
    }
    
    /**
     * 
     * @param model   模型
     * @param filler   填充者
     * @throws Exception
     */
    public ModelBuilderImpl(DataAnalyseModel model, ModelFiller<DataAnalyseModel> filler) throws Exception
    {
        this(model, true, null, filler);
    }
    
    /**
     * 
     * @param model   模型
     * @param sourceTable   数据源
     * @throws Exception
     */
    public ModelBuilderImpl(DataAnalyseModel model, DataTable sourceTable) throws Exception
    {
        this(model, true, sourceTable, null);
    }
    
    private ModelBuilderImpl(DataAnalyseModel model, boolean fillData, DataTable sourceTable, ModelFiller<DataAnalyseModel> filler) throws Exception
    {
        super();
        Assert.isNotNull(model, "模型信息为空！");
        // 判断模型合法性
        if (model.isXGroupHasField())
        {
            Assert.isFalse(model.isTransRowCol(), "X，Y维度不能同时有统计指标！");
        } else
        {
            Assert.isTrue(model.isTransRowCol(), "模型的统计指标定义为空！");
        }
        this.model = model;
        this.fillData = fillData;
        if (filler != null)
        {
            this.model.setModelFiller(filler);
        }
        if (sourceTable != null)
        {
            this.model.setDataSourceTable(sourceTable);
        }
    }

    @Override
    public DataTable buildAsDataTable() throws Exception
    {
        if (table != null)
        {
            return table;
        }
        if (fillData)
        {
            table = model.toDataTable();
        } else
        {
            table = model.toDataTableOnlyStruct();
        }
        this.headerConfigs = model.getHeaderConfigs();
        return table;
    }
    
    @Override
    public void setResultData(DataTable table, List<ReportHeader> headerConfigs) throws Exception
    {
        this.table = table;
        this.headerConfigs = headerConfigs;
    }
    
    @Override
    public String buildHeaderAsHtml() throws Exception
    {
        if (table == null)
        {
            buildAsDataTable();
        }
        // 处理
        return ModelUtil.transRegularDataTable2htmlheader(table, createHtmlConfig());
    }

    @Override
    public String buildAsHtml() throws Exception
    {
        return buildAsHtml(true);
    }
    
    @Override
    public String buildAsHtml(boolean withTitle) throws Exception
    {
        if (table == null)
        {
            buildAsDataTable();
        }
        String result = ModelUtil.transRegularDataTable2html(table, createHtmlConfig(), withTitle);
        return result;
    }
    
    @Override
    public String buildChartData(String chartId, boolean animation) throws Exception
    {
        List<DataChartModel> chartModels = model.getDataChartModels();
        if (CoreUtil.isEmpty(chartId) || chartModels == null || chartModels.isEmpty())
        {
            return null;
        }
        if (table == null)
        {
            buildAsDataTable();
        }
        if (table == null)
        {
            return null;
        }
        for (DataChartModel chartModel : chartModels)
        {
            if (chartId.equals(chartModel.getId()))
            {
                chartModel.setDataTable(table);
                return chartModel.toChartData(animation);
            }
        }
        return null;
    }

    @Override
    public String buildAsJson() throws Exception
    {
        return null;
    }

    @Override
    public byte[] exportData() throws Exception
    {
        if (table == null)
        {
            buildAsDataTable();
        }
        return new DataSet2Excel.Builder().addData(table).setBookConfig(createWorkBookConfig()).build().exportExcel();
    }
    
    /**
     * 创建ds的WorkBookConfig
     * @return
     * @throws Exception 
     */
    @Override
    public WorkBookConfig createWorkBookConfig() throws Exception
    {
        if (headerConfigs == null || headerConfigs.isEmpty())
        {
            // 没有表头配置，则自动构建
            return null;
        }
        if (table == null)
        {
            return null;
        }
        // 拷贝一份,因为导出宽度会放大
        List<ReportHeader> tempHeader = DeepCopyUtil.deepCopy(headerConfigs); 
        
        WorkBookConfig result = new WorkBookConfig();
        SheetConfig sheetConfig = result.newSheetConfig(table.getTableName());
        // 计算合并配置
        sheetConfig.setCombineConfigs(ModelUtil.calRegularCombineConfigs(table));
        // 表头表列相关信息
        sheetConfig.setTitle(table.getTableName());
        // 设置SheetConfig并重新计算宽度
        ExcelHtmlUtil.setSheetConfig(sheetConfig, tempHeader, true);
        sheetConfig.setLeftHeader(table.getLeftHeader());
        sheetConfig.setRightHeader(table.getRightHeader());
        sheetConfig.setHeaderConfigs(tempHeader);
        result.getSheetConfigs().add(sheetConfig);
        return result;
    }
    
    /**
     * 构建HtmlConfig
     * @return
     * @throws Exception
     */
    @Override
    public HtmlConfig createHtmlConfig() throws Exception
    {
        if (headerConfigs == null || headerConfigs.isEmpty())
        {
            // 没有表头配置，则自动构建
            return null;
        }
        if (table == null)
        {
            return null;
        }
        HtmlConfig result = new HtmlConfig();
        result.setTableClass(CoreUtil.parseStr(table.getTag()));
        result.setHeaderConfigs(headerConfigs);
        result.setCombineColumnConfigs(ModelUtil.calRegularCombineConfigs(table));
        return result;
    }

    @Override
    public DataAnalyseModel getModel()
    {
        return model;
    }

    public void setModel(DataAnalyseModel model)
    {
        this.model = model;
        // 清空数据
        this.table = null;
        this.headerConfigs = null;
    }

    public boolean isFillData()
    {
        return fillData;
    }

    public void setFillData(boolean fillData)
    {
        // 值变需要清空原结果
        if (fillData != this.fillData)
        {
            table = null;
        }
        this.fillData = fillData;
    }

}
